package model

import (
	"errors"
	"fmt"
	"project/schedule/util"
	"strconv"
)

func AllocateUnProposed(g *General, p *Project) error {
	projectScale := util.Scale(p.ProposedDay, g.ProjectScale)
	departmentProposedStartDate := g.Department[p.Department].ProposedStartDate
	for {
		// 若department_start_date非工作日, 则往后加一天, 确保项目起始日期是工作日
		if _, ok := util.WorkDayValue2Index[departmentProposedStartDate]; !ok {
			nextDayIndex := util.AllDayValue2Index[departmentProposedStartDate] + 1
			if nextDayIndex == 1 {
				return errors.New(fmt.Sprintf("%s没有可行解", p.Name))
			}
			departmentProposedStartDate = util.AllDayIndex2Value[nextDayIndex]
			continue
		}
		// 若是外地出差项目, 并且不是周一进场, 则往后加一天
		year, _ := strconv.ParseInt(departmentProposedStartDate[2:4], 10, 64)
		month, _ := strconv.ParseInt(departmentProposedStartDate[4:6], 10, 64)
		day, _ := strconv.ParseInt(departmentProposedStartDate[6:], 10, 64)
		if !p.IsLocal && util.WhichDay(int(year), int(month), int(day)) != "周一" {
			nextDayIndex := util.AllDayValue2Index[departmentProposedStartDate] + 1
			if nextDayIndex == 1 {
				return errors.New(fmt.Sprintf("%s没有可行解", p.Name))
			}
			departmentProposedStartDate = util.AllDayIndex2Value[nextDayIndex]
			continue
		}
		departmentProposedEndDate := util.WorkDayIndex2Value[util.WorkDayValue2Index[departmentProposedStartDate]+p.ProposedDay-1]
		allocation := &Allocation{}
		// 先分配本部门
		for employee, employeeInfo := range g.Staff {
			if employeeInfo.Department != p.Department {
				continue
			}
			if util.CrossOverMulti(departmentProposedStartDate, departmentProposedEndDate, employeeInfo.Vacation) {
				continue
			}
			if util.CrossOverMulti(departmentProposedStartDate, departmentProposedEndDate, employeeInfo.WorkRegion) {
				continue
			}
			Allocating(g, p, allocation, employeeInfo, employee, projectScale, departmentProposedStartDate, departmentProposedEndDate)
		}
		// 后分配其他部门
		for employee, employeeInfo := range g.Staff {
			if employeeInfo.Department == p.Department {
				continue
			}
			if util.CrossOverMulti(departmentProposedStartDate, departmentProposedEndDate, employeeInfo.Vacation) {
				continue
			}
			if util.CrossOverMulti(departmentProposedStartDate, departmentProposedEndDate, employeeInfo.WorkRegion) {
				continue
			}
			if !employeeInfo.LendOut {
				continue
			}
			Allocating(g, p, allocation, employeeInfo, employee, projectScale, departmentProposedStartDate, departmentProposedEndDate)
		}
		if allocation.GroupJudge == "" || allocation.GroupLeader == "" {
			nextDayIndex := util.AllDayValue2Index[departmentProposedStartDate] + 1
			if nextDayIndex == 1 {
				return errors.New(fmt.Sprintf("%s没有可行解", p.Name))
			}
			departmentProposedStartDate = util.AllDayIndex2Value[nextDayIndex]
			continue
		}

		outPack := g.Project[p.Name].OutPack
		x, _ := strconv.ParseInt(departmentProposedStartDate[4:6], 10, 64)
		groupLeaderJudgeSlice := make([]string, 0)
		groupLeaderJudgeSlice = append(groupLeaderJudgeSlice, allocation.GroupJudge)
		groupLeaderJudgeSlice = append(groupLeaderJudgeSlice, allocation.GroupLeader)
		different := len(util.Duplicate(groupLeaderJudgeSlice))
		if outPack != 0 && int(x) >= outPack {
			lack := p.ProposedPerson - different
			for i := 0; i < lack; i++ {
				allocation.GroupMember = append(allocation.GroupMember, "wb")
			}
		} else {
			lack := p.ProposedPerson - len(allocation.GroupMember) - different
			for i := 0; i < lack; i++ {
				allocation.GroupMember = append(allocation.GroupMember, "wb")
			}
		}

		allocateDetail := make(map[string]map[string]string)

		// 若组长和主审为同一个人, 则用主审来更新
		if allocation.GroupLeader == allocation.GroupJudge {
			before, after := util.AuditDay(p.ProposedDay, "主审", g.AuditRule)
			startDate := util.AllDayIndex2Value[util.AllDayValue2Index[departmentProposedStartDate]-before]
			endDate := util.AllDayIndex2Value[util.AllDayValue2Index[departmentProposedEndDate]+after]
			allocateDetail[allocation.GroupJudge] = make(map[string]string)
			allocateDetail[allocation.GroupJudge]["startDate"] = startDate
			allocateDetail[allocation.GroupJudge]["endDate"] = endDate
			g.Staff[allocation.GroupJudge].WorkRegion = append(g.Staff[allocation.GroupJudge].WorkRegion,
				allocateDetail[allocation.GroupJudge])
		} else {
			// 更新组长的workRegion
			before, after := util.AuditDay(p.ProposedDay, "组长", g.AuditRule)
			startDate := util.AllDayIndex2Value[util.AllDayValue2Index[departmentProposedStartDate]-before]
			endDate := util.AllDayIndex2Value[util.AllDayValue2Index[departmentProposedEndDate]+after]
			allocateDetail[allocation.GroupLeader] = make(map[string]string)
			allocateDetail[allocation.GroupLeader]["startDate"] = startDate
			allocateDetail[allocation.GroupLeader]["endDate"] = endDate
			g.Staff[allocation.GroupLeader].WorkRegion = append(g.Staff[allocation.GroupLeader].WorkRegion,
				allocateDetail[allocation.GroupLeader])
			// 更新主审的workRegion
			before, after = util.AuditDay(p.ProposedDay, "主审", g.AuditRule)
			startDate = util.AllDayIndex2Value[util.AllDayValue2Index[departmentProposedStartDate]-before]
			endDate = util.AllDayIndex2Value[util.AllDayValue2Index[departmentProposedEndDate]+after]
			allocateDetail[allocation.GroupJudge] = make(map[string]string)
			allocateDetail[allocation.GroupJudge]["startDate"] = startDate
			allocateDetail[allocation.GroupJudge]["endDate"] = endDate
			g.Staff[allocation.GroupJudge].WorkRegion = append(g.Staff[allocation.GroupJudge].WorkRegion,
				allocateDetail[allocation.GroupJudge])
		}

		// 更新组员的workRegion
		before, after := util.AuditDay(p.ProposedDay, "组员", g.AuditRule)
		startDate := util.AllDayIndex2Value[util.AllDayValue2Index[departmentProposedStartDate]-before]
		endDate := util.AllDayIndex2Value[util.AllDayValue2Index[departmentProposedEndDate]+after]
		for _, staff := range allocation.GroupMember {
			if staff == "wb" {
				continue
			}
			allocateDetail[staff] = make(map[string]string)
			allocateDetail[staff]["startDate"] = startDate
			allocateDetail[staff]["endDate"] = endDate
			g.Staff[staff].WorkRegion = append(g.Staff[staff].WorkRegion, allocateDetail[staff])
		}

		// 补全信息
		allocation.DepartmentProposedStartDate = g.Department[p.Department].ProposedStartDate
		allocation.ProjectProposedDay = p.ProposedDay
		allocation.ProjectProposedPerson = p.ProposedPerson
		allocation.ProjectProposedStartDate = ""
		allocation.ProjectAllocatedStartDate = departmentProposedStartDate
		allocation.ProjectAllocatedEndDate = departmentProposedEndDate
		allocation.ProjectDepartment = p.Department
		allocation.ProjectAllocatedDetail = allocateDetail
		g.Allocation[p.Name] = allocation
		return nil
	}
}
